#pragma once
#include "smartalloc_wrap.h"
#include "TubeTruckTypes.h"

#include <pthread.h>
#include <vector>
#include <list>
#include <string>
#include <exception>

#define STRFY(X) #X
#define STRFY1(X) STRFY(X)
#define AT (std::string(__FILE__ ":" STRFY1(__LINE__) " - ")+__PRETTY_FUNCTION__)

#define FOR_EACH_BOUND(it, list, bnd) for(decltype((list).end()) it = (list).lower_bound(bnd); it != (list).upper_bound(bnd); ++it)
#define FOR_EACH(it, list) for(decltype((list).end()) it = (list).begin();  it != (list).end(); ++it)
#define FOR_EACH_R(it, list) for(decltype((list).rend()) it = (list).rbegin();  it != (list).rend(); ++it)

class msg_exception : public std::exception { 
public:
   msg_exception(const char * m) : msg(m) {}
   msg_exception(const std::string & m) : msg(m) {}
   ~msg_exception() throw() {}
   std::string msg;
   virtual const char* what() const throw() {
      return msg.c_str();
   }
};

#define Exception(x) class x : public msg_exception { \
public:                                      \
   x(const char *m) : msg_exception(m) {} \
   x(const std::string & m) : msg_exception(m) {} \
}

Exception(EINTR_exception);
Exception(parsing_exception);
Exception(verification_exception);
Exception(identity_exception);
Exception(encryption_exception);

#undef Exception

std::pair<std::string, std::string> fmtstrs(const std::vector<byte> &vec, uint32_t & addr);
std::pair<std::string, std::string> fmtstrs(const std::vector<byte> &vec);
std::ostream & operator <<(std::ostream &os, const std::vector<byte> &vec);



namespace TTP {

   class lockObj {
      pthread_mutex_t * lockPtr;
   public:
      lockObj (pthread_mutex_t * lock) : lockPtr(lock) { pthread_mutex_lock(lockPtr); }
      ~lockObj () { pthread_mutex_unlock(lockPtr); }
   };

}

